import { readFileSync } from 'fs-extra';
import { join } from 'path';
import { createApp } from 'vue';
import * as fs from 'fs';
import * as path from 'path';
import * as os from 'os';
import { exec } from 'child_process';


const system = {
    linux: 'Linux',
    mac: 'Darwin',
    window: 'Windows_NT',
}

let totalFiles = [];
let successFiles: string[] = [];
let failFiles: string[] = [];
let totalBeforeSize = 0;
let totalNowSize = 0;
module.exports = Editor.Panel.define({
    listeners: {
        show() { console.log('show'); },
        hide() { console.log('hide'); },
    },
    template: readFileSync(join(__dirname, '../../../../static/template/default/index.html'), 'utf-8'),
    style: readFileSync(join(__dirname, '../../../../static/style/default/index.css'), 'utf-8'),
    $: {
        app: '#app',
        text: '#text',
    },
    methods: {
        hello() {
            if (this.$.text) {
                this.$.text.innerHTML = 'hello';
                console.log('[cocos-panel-html.default]: hello');
            }
        },
    },
    ready() {
        if (this.$.text) {
            this.$.text.innerHTML = 'CocosCreator一键压缩工具';
        }
        if (this.$.app) {
            const app = createApp({});
            app.component('my-counter', {
                template: readFileSync(join(__dirname, '../../../../static/template/vue/counter.html'), 'utf-8'),
                data() {
                    return {
                        counter: "0.0.1.20211214",
                        lastColorIdx: 0,
                        colorList: ['#383838', '#2F2F2F'],


                    };
                },
                created() {
                },
                mounted() {
                    console.log('ready', this)
                    //@ts-ignore
                    window['app'] = this;
                    this.initId(this.$el, this.$)
                    // console.log(this.$.progress)
                    this.setProgress(0)
                    this.setState('就绪')
                    totalBeforeSize = 0;
                    totalNowSize = 0;
                    totalFiles = [];
                    successFiles = [];
                    failFiles = [];

                    this.$.compress_result.value = 0
                },
                methods: {

                    initId(node: Element, target: any): void {
                        this.getChildrenRecursive(node).forEach((v: Element) => {
                            if (v && v.id != '') {
                                target[v.id] = v;
                            }
                        })
                    },
                    getChildById(node: Element, id: string): Element | null {
                        let res = this.getChildrenRecursive(node).find((v: Element) => {
                            return v && v.id == id;
                        }) || null
                        return res;
                    },

                    getChildrenRecursive(node: Element): Element[] {
                        let children: Element[] = [];
                        for (let i = 0; i < node.children.length; i++) {
                            children.push(node.children[i]);
                        }
                        if (node.children && node.children.length) {
                            for (let i = 0; i < node.children.length; i++) {
                                children = children.concat(this.getChildrenRecursive(node.children[i]));
                            }
                        }
                        return children;
                    },

                    getImagePathListRecursive(filePath: string, isCheckCompressState: boolean) {
                        // console.log('getImagePathListRecursive', filePath)
                        let pathList: string[] = [];
                        if (fs.existsSync(filePath)) {
                            if (fs.statSync(filePath).isFile()
                                && (!isCheckCompressState || !this.isCompressed(filePath))
                                && filePath.match(/.png$/)
                            ) {
                                // console.log(isCheckCompressState, !isCompressed(filePath))
                                pathList.push(filePath);
                            } else if (fs.statSync(filePath).isDirectory()) {
                                let fileList = fs.readdirSync(filePath)
                                if (fileList.length) {
                                    fileList.forEach(v => {
                                        let newfilePath = `${filePath}/${v}`;
                                        pathList = pathList.concat(this.getImagePathListRecursive(newfilePath, isCheckCompressState));
                                    })
                                }
                            }
                        }
                        return pathList;
                    },

                    /**是否是png */
                    isPng(filePath: string) {
                        return filePath.match(/.png$/);
                    },
                    /**压缩函数 */
                    compressImg(filePath: string): Promise<any> {
                        return new Promise((resolve, reject) => {

                            if (filePath.match(/.meta$/)) {
                                reject(null)
                                return
                            }
                            if (!this.isPng(filePath)) {
                                this.print('不是png文件，略过 ' + path.basename(filePath))
                                reject(null)
                                return;
                            }
                            // if (!isCompressed(filePath)) {
                            // this.showLog('压缩文件' + filePath)
                            console.log('filePath' + filePath)
                            totalFiles.push(filePath);
                            let beforeSize = fs.statSync(filePath).size;
                            totalBeforeSize += beforeSize;
                            this.pngquantCompress(filePath).then((error: Error) => {
                                let nowSize = fs.statSync(filePath).size;
                                totalNowSize += nowSize;
                                if (error) {
                                    failFiles.push(filePath);
                                    this.print('失败 ' + path.basename(filePath))
                                } else {
                                    successFiles.push(filePath);
                                    // this.print('成功 ' + path.basename(filePath))

                                    let compressEffectPercent = (beforeSize - nowSize) / beforeSize * 100;
                                    this.print(`压缩成功： ${filePath} : <ui-progress style="margin:auto;height:20px;width:100px" value="${compressEffectPercent}">${compressEffectPercent}%</ui-progress>`)
                                }

                                // this.print(totalFiles.length, successFiles.length, failFiles.length)
                                if (totalFiles.length == (successFiles.length + failFiles.length)) {
                                    this.finishLog();
                                }
                                resolve(null)
                            })
                        })
                    },

                    /**结束log */
                    finishLog() {
                        this.print('/**********压缩全部完成******************/');
                        this.print('压缩成功文件' + successFiles.length + '个' + successFiles);
                        this.print('压缩失败文件' + failFiles.length + '个' + failFiles);
                        this.print('共' + totalFiles.length + '个');
                        // this.print('无应答', totalFiles.length - (successFiles.length + failFiles.length), '个');
                        // this.print("已请求次数", compressionsThisMonth);
                        let compressEffectPercent = (totalBeforeSize - totalNowSize) / totalBeforeSize * 100;
                        this.print(`总体压缩效果： -${compressEffectPercent}%`)
                        // if (buildCallback) buildCallback();
                        this.$.compress_result.value = compressEffectPercent;
                    },
                    /**压缩方式 */
                    // function compressFunc(filePath: string): Promise { }

                    /**是否压缩过 */
                    isCompressed(filePath: string) {
                        let buf = fs.readFileSync(filePath)
                        let bitsPerPixel = buf[24] & 0xff;
                        if (buf[25] == 2) {
                            bitsPerPixel *= 3;
                        } else if (buf[25] == 6) {
                            bitsPerPixel *= 4;
                        }
                        return bitsPerPixel < 24;
                    },


                    /**pngquant压缩 */
                    pngquantCompress: function (filePath: string): Promise<any> {
                        return new Promise((resolve, reject) => {

                            let cmd;
                            let TOOL_PATH = join(__dirname, '../../../../tool')
                            if (os.type() == system.window) {
                                cmd = `${TOOL_PATH}/pngquant-win.exe --quality=50-80 --force --verbose 256 ${filePath} --output ${filePath}`;
                            } else {
                                // 修改文件权限
                                exec(`chmod a+x ./${TOOL_PATH}/pngquant-mac`);
                                cmd = `./${TOOL_PATH}/pngquant-mac --force --verbose 256 ${filePath} --output ${filePath}`;
                            }

                            exec(cmd, (error, stdout, stderr) => {
                                if (resolve) resolve(error)
                            })
                        })
                    },

                    compress() {
                        this.$.compress_result.value = 0
                        this.$.progress.value = 0
                        // this.setProgress(0)
                        totalBeforeSize = 0;
                        totalNowSize = 0;
                        totalFiles = [];
                        successFiles = [];
                        failFiles = [];

                        let list = this.getImagePathListRecursive(Editor.Project.path + '/assets', true)
                        let count = 0;
                        if (list.length) {
                            
                            list.forEach(async (v: Element) => {
                                await this.compressImg(v)
                                count++;
                                // this.print(count + ' ' + list.length + ' ' + count / list.length * 100)
                                this.$.progress.value = count / list.length * 100
                            })
                        } else {
                            this.print('没有需要压缩的图片')
                        }

                    },
                    setState(str: string) {
                        this.$.desc.innerText = '状态：' + str
                    },
                    clearLog() {
                        this.getChildrenRecursive(this.$.logWrap).forEach((v: Element) => {
                            this.$.logWrap.removeChild(v)
                        })
                    },
                    setProgress(num: number) {
                        if (num < 0) num = 0
                        if (num > 100) num = 100
                        this.$.progress.value = num;
                    },

                    print(...msg: any[]) {
                        msg.forEach(v => {
                            this.showLog(v)
                        })
                    },

                    showLog(msg = 'testLog') {
                        let p = document.createElement('p');
                        p.innerHTML = '[console.log]: ' + msg;
                        // console.log('logWrap', msg)
                        let logWrap = this.$.logWrap
                        let color = this.$data.colorList[this.$data.lastColorIdx];
                        p.style.backgroundColor = color
                        p.style.margin = 'auto'
                        p.style.color = '#C3C3C3'
                        p.style.width = 'auto'

                        // console.log('logWrap', logWrap)
                        logWrap?.appendChild(p);
                        this.$data.lastColorIdx++;
                        if (this.$data.lastColorIdx >= this.colorList.length) {
                            this.$data.lastColorIdx = 0;
                        }
                    },
                },
            });
            app.mount(this.$.app);
        }
    },
    beforeClose() { },
    close() { },
});


